/**
 * Copyright 2007 Igor Chaves Cananéa
 *
 * This file is part of PBSFW
 *
 * PBSFW is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * PBSFW is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef _SIM_UTIL_TRACE_H_
#define _SIM_UTIL_TRACE_H_

#include <fstream>
#include <cstdarg>
using namespace std;

namespace util {
	enum DebugLevel { PARANOID, ERROR, WARNING, INFORMATION };
	class Trace {
		private:
			DebugLevel debugLevel;
			const char *className;
			const char *methodName;

			static unsigned count;		//!< nested call count

			void do_debug(const char *msg) const;
			void do_debug(double value, const char *msg) const;
			void do_debugf(const char *msg, va_list ap) const;
			const char *indent() const;
            const char *time() const;

		public:
			static DebugLevel currentLevel;
			static bool active;
			static ostream &out;
			static bool indentation;		//!< if want see shifted-right messages (true) or number (false)
			static unsigned indentLen;	//!< number of identation spaces for each nested call

			Trace(const char *className, const char *methodName);
			Trace(DebugLevel debugLevel, const char *className,
				  const char *methodName);

			~Trace();

			bool isActive() const {
				return Trace::active && this->debugLevel >= Trace::currentLevel;
			}

			void debug(const char *msg) const {
				if (this->isActive()) {
					this->do_debug(msg);
				}
			}

			void debug(double value, const char *msg = "") const {
				if (this->isActive()) {
					this->do_debug(value, msg);
				}
			}

			void debugf(const char *msg, ...) const {
				if (this->isActive()) {
					va_list ap;

					va_start(ap, msg);
					this->do_debugf(msg, ap);
					va_end(ap);
				}
			}
	};
};

#endif
